#include "../include/SceneReader.h"
#include "../include/Sphere.h"
#include "../include/Triangle.h"
#include "../include/pVect.h"
#include "../include/Materiaux.h"
#include "../include/ModeleObj.h"
#include "../include/Plan.h"
#include "../include/SurfaceLight.h"
#include "../include/SpotLight.h"
#include <list>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

SceneReader::SceneReader()
{
    //ctor
}

/**
* Methode permettant de lire dans un fichier une scene
* @param fichier le nom du fichier (format .scene)
* @return une scene
*/
SceneReader::SceneReader(char* fichier){
    //initialisation de valeure par défault
    this->fond = Color::BLACK;
    this->aoRayon = 0;

    string STRING;
	ifstream infile;
	infile.open (fichier);
	vector<Materiaux> listMateriaux;
        while(!infile.eof())
        {
	        getline(infile,STRING);
            istringstream iss(STRING);
            string sub;
            if(iss){
                iss>>sub;
                // m la ligne décrit un materiaux
                if(sub == "m"){
                    float r, g, b, k, miroir, i;
                    int t;
                    iss>>r;
                    iss>>g;
                    iss>>b;
                    iss>>k;
                    iss>>t;
                    iss>>miroir;
                    iss>>i;
                    Materiaux toto(Color(r,g,b),k,t);
                    toto.miroir = miroir;
                    toto.indice = i;
                    listMateriaux.push_back(toto);
                }
                // s la ligne décrit un sphere
                if(sub == "s"){
                    float x,y,z,r;
                    int m;
                    iss>>x;
                    iss>>y;
                    iss>>z;
                    iss>>r;
                    iss>>m;
                    Materiaux mat = listMateriaux.at(m-1);
                    this->lObject.push_back(new Sphere(pVect(x,y,z),r,mat));
                }
                // t la ligne décrit un triangle
                if(sub == "t"){
                    float x1,y1,z1,x2,y2,z2,x3,y3,z3;
                    int m;
                    iss>>x1;
                    iss>>y1;
                    iss>>z1;
                    iss>>x2;
                    iss>>y2;
                    iss>>z2;
                    iss>>x3;
                    iss>>y3;
                    iss>>z3;
                    iss>>m;
                    Materiaux mat = listMateriaux.at(m-1);
                    this->lObject.push_back(new Triangle(pVect(x1,y1,z1),pVect(x2,y2,z2),pVect(x3,y3,z3),mat));
                }
                // l la ligne décrit une lumière
                if(sub == "l"){
                    float x,y,z,r,g,b,p;
                    iss>>x;
                    iss>>y;
                    iss>>z;
                    iss>>r;
                    iss>>g;
                    iss>>b;
                    iss>>p;
                    this->lLight.push_back(new Light(pVect(x,y,z), Color(r,g,b), p));
                }
                // sl la ligne décrit une lumière surfacique (soleil)
                if(sub == "sl"){
                    float x,y,z,r,g,b,p, rsoleil;
                    int nbrr;
                    iss>>x;
                    iss>>y;
                    iss>>z;
                    iss>>r;
                    iss>>g;
                    iss>>b;
                    iss>>p;
                    iss>>nbrr;
                    iss>>rsoleil;
                    this->lLight.push_back(new SurfaceLight(pVect(x,y,z), Color(r,g,b), p, nbrr, rsoleil));
                }
                //sp la ligne décrit une lumière surfacique (spot)
                if(sub == "sp"){
                    float x,y,z,r,g,b,p, rsoleil, dx,dy,dz, a;
                    int nbrr;
                    iss>>x;
                    iss>>y;
                    iss>>z;
                    iss>>r;
                    iss>>g;
                    iss>>b;
                    iss>>p;
                    iss>>nbrr;
                    iss>>rsoleil;
                    iss>>dx;
                    iss>>dy;
                    iss>>dz;
                    iss>>a;
                    this->lLight.push_back(new SpotLight(pVect(x,y,z), Color(r,g,b), p, nbrr, rsoleil, pVect(dx,dy,dz), a));
                }
                // o la ligne décrit un model obj
                if(sub == "o"){
                    char* fichier = new char[128];
                    float x,y,z;
                    int m;
                    iss>>x;
                    iss>>y;
                    iss>>z;
                    iss>>fichier;
                    iss>>m;
                    Materiaux mat = listMateriaux.at(m-1);
                    this->lObject.push_back(new ModeleObj(fichier, pVect(x,y,z), mat));
                }
                // p la ligne décrit un plan
                if(sub == "p"){
                    float x,y,z, a,b,c;
                    int m;
                    iss>>x;
                    iss>>y;
                    iss>>z;
                    iss>>a;
                    iss>>b;
                    iss>>c;
                    iss>>m;
                    Materiaux mat = listMateriaux.at(m-1);
                    this->lObject.push_back(new Plan(pVect(x,y,z),pVect(a,b,c), mat));
                }
                // pv la ligne décrit un plan carractérisé par deux vecteurs
                if(sub == "pv"){
                    float x,y,z, a,b,c, d,e,f;
                    int m;
                    iss>>x;
                    iss>>y;
                    iss>>z;
                    iss>>a;
                    iss>>b;
                    iss>>c;
                    iss>>d;
                    iss>>e;
                    iss>>f;
                    iss>>m;
                    Materiaux mat = listMateriaux.at(m-1);
                    this->lObject.push_back(new Plan(pVect(x,y,z),pVect(a,b,c),pVect(d,e,f), mat));
                }
                // réglage de la quantité d'anti aliasing
                if(sub == "aa"){
                    iss>>this->antialiasing;
                }
                // réglage du nombre de récursion maximum
                if(sub == "maxr"){
                    iss>>this->maxrecurs;
                }
                // réglage de la taille de l'image finale
                if(sub == "img"){
                    iss>>this->imghauteur;
                    iss>>this->imglargeur;
                }
                // réglage des caractéristiques de la caméra (position, orientation, focale)
                if(sub == "cam"){
                    float x,y,z,a,b,c;
                    iss>>x;
                    iss>>y;
                    iss>>z;
                    iss>>a;
                    iss>>b;
                    iss>>c;
                    iss>>this->focale;
                    this->campos = pVect(x,y,z);
                    this->camdir = pVect(a,b,c);
                }
                //choix couleur du fond
                if(sub == "fond"){
                    float r,g,b;
                    iss>>r;
                    iss>>g;
                    iss>>b;
                    this->fond=Color(r,g,b);
                }
                //choix ambiante oclusion
                if(sub == "ao"){
                    int nbRayon;
                    iss>>nbRayon;
                    this->aoRayon=nbRayon;
                }
            }
        }
	infile.close();
}

SceneReader::~SceneReader()
{
    //dtor
}
